home *** CD-ROM | disk | FTP | other *** search
/ No Fragments Archive 12: Textmags & Docs / nf_archive_12.iso / MAGS / SOURCES / ATARI_SRC.ZIP / atari source / FALCON / ACC / OUTLINE.ACC / MOVER.C < prev    next >
Encoding:
C/C++ Source or Header  |  2001-02-10  |  51.3 KB  |  1,798 lines

  1. /* FILE:  MOVER.C
  2.  *==========================================================================
  3.  * DATE:  May  16, 1990
  4.  *        July 11, 1991
  5.  *      July  9, 1992 Yup- 1992 - no kidding
  6.  *            IF AES version is >= 3.2, use MFsave, else skip
  7.  *      Dec   9, 1992 Modifications for FONTS.ACC
  8.  *      Dec  15, 1992 Remove Bitmap and Device stuff
  9.  *
  10.  * DESCRIPTION: MOVER
  11.  *
  12.  * INCLUDE FILE: MOVER.H
  13.  */
  14.  
  15.  
  16. /* INCLUDE FILES
  17.  *==========================================================================
  18.  */
  19. #include <sys\gemskel.h> 
  20. #include <stdlib.h>
  21.  
  22. #include "country.h"
  23. #include "fonthead.h"
  24. #include "fonts.h"
  25. #include "fsmio.h"
  26.  
  27. #include "front.h"
  28. #include "mainstuf.h"
  29. #include "text.h"
  30. #include "sliders.h"
  31. #include "custom.h"
  32. #include "inactive.h"
  33.  
  34.  
  35. struct foobar {
  36.     WORD    dummy;
  37.     WORD    *image;
  38.     };
  39. extern int AES_Version;
  40. extern int gl_ncolors;
  41.  
  42.  
  43. /* PROTOTYPES
  44.  *==========================================================================
  45.  */
  46.  
  47. /* Interface Routines */
  48. void    mover_setup( FON_PTR list_ptr, int font_count,
  49.              int base, int slider, int up, int down,
  50.              int first_obj, int last_obj, int base_obj,
  51.              int start_index, int num_rows );
  52.  
  53. void mover_button( int obj, int clicks );
  54. BOOLEAN mover_keys( void );
  55.  
  56. void    Undo_Fnodes( FON_PTR ptr, FON_PTR flag );
  57. void    ClearFnodes( FON_PTR ptr );
  58. BOOLEAN IsChanged( FON_PTR ptr );
  59. FON_PTR    Find_Fnode( FON_PTR ptr, int index );
  60.  
  61.  
  62. /* Slit handling */
  63. void      Draw_Slit( void );
  64. void    Draw_Hot( void );
  65. void      slit_offset_adjust( FON_PTR ptr, int value, FON_PTR array[] );
  66. void    Assign_Slit( FON_PTR ptr, FON_PTR array[] );
  67. void    Blit_Slits( int old_slit, int new_slit );
  68.  
  69.  
  70. void    Make_Hot_Spots( int top_object );
  71.  
  72. int    Get_Findex( FON_PTR tptr, FON_PTR ptr );
  73. int    Get_Hot_Index( int *hot_index );
  74.  
  75.  
  76. FON_PTR    Hot_Old_New_Update( int index, FON_PTR Top_Node,
  77.                       int old_index, int findex,
  78.                       int Top_Obj, FON_PTR Slit_Array[] );
  79.  
  80. void    Old_Index_Handler( int old_index, int new_index, int findex,
  81.                   FON_PTR Top_Node, FON_PTR Base_Node,
  82.                   int Above_Obj, int Below_Obj );
  83. void    New_Index_Handler( int old_index, int new_index, int findex,
  84.                FON_PTR Top_Node, FON_PTR Base_Node,
  85.                int Above_Obj, int Below_Obj );
  86. void    Hot_Scroll( FON_PTR Xptr, int cur_slit, int First_Obj, int End_Obj );
  87. void    Do_Hot_Scroll( int obj, FON_PTR Top_Node, FON_PTR base_node,
  88.                int Top_Obj, int Total,
  89.                       int Xbase, int Xslider, int *cur_slit,
  90.                FON_PTR Slit_Array[], void (*foo)() );
  91.  
  92. int     rub_wait( GRECT *obj, int dir, int state );
  93.                       
  94. void    Hot_Slide( OBJECT *tree, int base, int slider, int obj,
  95.                   int inc, int min, int max, int *numvar,
  96.                int direction, GRECT *rect, void (*foo)() );
  97.  
  98. int    FindNumSelected( FON_PTR ptr );
  99. FON_PTR    FindFirstFont( FON_PTR ptr );
  100.  
  101.  
  102. void    CheckHotFront( FON_PTR Head_Node );
  103. void    CheckHotAvailable( FON_PTR Head_Node );
  104. void    CheckHotPoints( FON_PTR Head_Node );
  105.  
  106.  
  107. /* DEFINES
  108.  *==========================================================================
  109.  */
  110.  
  111.  
  112. /* GLOBALS
  113.  *==========================================================================
  114.  */
  115.  
  116. /* MOVER/RENAME VARIABLES */
  117.  
  118. /* The blank string for the filenames    */
  119. char fblank[] = "                           ";
  120. char fblank2[] = "   ";
  121. #if 0
  122. char fblank3[] = "            ";
  123. #endif
  124.  
  125. FON_PTR  hdptr = NULL;        /* Active FNODE Pointer Head         */
  126. int      Total;            /* Total 'Active' filenames         */
  127. FON_PTR  Active_Slit[25];    /* These are arrays of FNODE pointers    
  128.                      * which are used to point to the fnode
  129.                      * that is in its slot. That way we can
  130.                      * quickly get the information from the
  131.                      * node. If the fnode is NULL, we set the
  132.                      * text to point to fblank[]
  133.                      */
  134.                      
  135. int   Cur_Slit, Old_Slit;    /* The index INTO the filename linked list
  136.                  * so that we can count INTO it and find
  137.                  * an offset for the top node. I = Inactive
  138.                  * and A = Active
  139.                  */
  140. GRECT hot_spot[25];        /* Grect(s) for the 6 filename buttons plus
  141.                  * one above and one below. They are 
  142.                  * created ONLY when a filename button 
  143.                  * object is selected: LINE0 - LINE5
  144.                  */
  145. int   hot_index;           /* Index for Hot_Spot[] 
  146.                  * Hot_Spot[] is an array of grects which is
  147.                  * defined when the user clicks on a filename.
  148.                  * The GRECTS are the boxes where we look to
  149.                  * see where the mouse IS, and WAS so that
  150.                  * we can select, deselect or scroll the
  151.                  * filenames.
  152.                  */
  153. FON_PTR Base_Node;         /* The node the scroll started with */
  154. int     new_index;        /* NEW index into linked list ( zero based ) */
  155. int     findex;            /* node index INTO the linked list ( zero based )
  156.                  * This is the one that was first clicked on
  157.                  * and started all of the scrolling.
  158.                  * NOTE: findex's node is Base_Node.
  159.                  */
  160.                 
  161. char src_fname[128];        /* Active and Inactive source paths */
  162. char dst_fname[128];
  163.  
  164. FON  Point_Arena[ MAX_POINTS + 2 ];/* Arena for the Scrolling of point sizes */
  165. FON_PTR  Temp_Fon;
  166.             
  167.  
  168.     
  169. MFORM    mfOther;
  170.  
  171. /*
  172.    Below Variables are GLOBALS for the MOVER Routines so that
  173.    we can use more than one tree to perform with the sliders
  174.    NOTE: We must still have MAX_SLITS for each slider and
  175.          the slider must be VERTICAL.
  176. */
  177. int Mbase,Mslider;        /* Active Mover Base and Slider */
  178. int Mup, Mdown;            /* Active UP Button and Down Button*/
  179. int First_Obj;            /* First Object in Scroll Area : ie: LINE0 */
  180. int Base_Obj;            /* Parent Obj of Scroll Area Objects 0 - 5*/                
  181. int Obj_Beg, Obj_End;
  182. int MAX_SLITS;
  183.  
  184.  
  185. /* FUNCTIONS
  186.  *==========================================================================
  187.  */
  188.  
  189.  
  190. /*
  191.  *==========================================================================
  192.  * Interface Routines
  193.  *==========================================================================
  194.  */
  195.  
  196.  
  197. /* mover_setup()
  198.  *==========================================================================
  199.  * RETURNS TRUE - SUCCESS
  200.  *       FALSE- ERROR! ( probably memory allocation )
  201.  */
  202. void
  203. mover_setup( FON_PTR list_ptr, int font_count,
  204.          int base, int slider, int up, int down,
  205.          int first_obj, int last_obj, int base_obj,
  206.          int start_index, int num_rows )
  207. {
  208.     int i;
  209.  
  210.     hdptr = list_ptr;
  211.     Total = font_count;
  212.     MAX_SLITS   = num_rows;
  213.     
  214.     Mbase     = base;
  215.     Mslider    = slider;
  216.     Mup        = up;
  217.     Mdown    = down;
  218.     First_Obj    = first_obj;
  219.     Base_Obj    = base_obj;
  220.     Obj_Beg    = first_obj;
  221.     Obj_End    = last_obj;           
  222.     
  223.     for( i = 0; i < MAX_SLITS;i++ )
  224.     {
  225.         Active_Slit[i] = NULL;
  226. #if 0
  227.     /* For the CUSTOM Dialog Box, we need fblank to be shorter..*/
  228.     if( IsActiveTree( ad_custom ) )
  229.           TedText( First_Obj + i ) = fblank3;
  230. #endif
  231.  
  232.     if( IsActiveTree( ad_points ) )
  233.           TedText( First_Obj + i ) = fblank2;
  234.  
  235.     if( IsActiveTree( ad_front ) || IsActiveTree( ad_inactive ) )
  236.             TedText( First_Obj + i ) = fblank;
  237.     }
  238.         
  239.     if( Total > MAX_SLITS )
  240.     {
  241.        if( start_index > Total - MAX_SLITS )
  242.            start_index = Total - MAX_SLITS;
  243.     }
  244.     else
  245.        start_index = 0;
  246.        
  247.     slit_offset_adjust( hdptr, start_index, Active_Slit );
  248.  
  249.     if( start_index )
  250.         start_index = Get_Findex( hdptr, Active_Slit[0] );
  251.  
  252.     Old_Slit = Cur_Slit = start_index;
  253.     sl_size( tree, Mbase, Mslider, Total, MAX_SLITS, VERTICAL, 0 );
  254.     sl_y( tree, Mbase, Mslider, Cur_Slit,
  255.                   max( Total - MAX_SLITS, 0 ), 0, NULLFUNC );
  256. }
  257.  
  258.  
  259.  
  260.  
  261. /* mover_button()
  262.  *==========================================================================
  263.  * Handles the button events for the CPX Mover/Rename Function
  264.  * IN: int obj:        The RCS Object clicked on.
  265.  * OUT: BOOLEAN:   TRUE - Exit the CPX Mover Config
  266.  *           FALSE - Remain in the CPX Mover Config
  267.  */
  268. void
  269. mover_button( int obj, int clicks )
  270. {
  271.    MRETS mk;
  272.    int   ox,oy;
  273.    
  274.         Old_Slit = Cur_Slit;
  275.  
  276.     if( obj == Mup )
  277.     {        
  278.        sl_arrow( tree, Mbase, Mslider, Mup, -1,
  279.                      max( Total - MAX_SLITS, 0 ), 0,
  280.                      &Cur_Slit, VERTICAL, Draw_Slit );
  281.            return;                         
  282.         }                            
  283.  
  284.         if( obj == Mdown )
  285.         {
  286.            sl_arrow( tree, Mbase, Mslider, Mdown, 1,
  287.                     max( Total - MAX_SLITS, 0 ), 0,
  288.                     &Cur_Slit, VERTICAL, Draw_Slit );
  289.            return;                         
  290.         }                            
  291.  
  292.         if( obj == Mslider )
  293.         {
  294.            MF_Save();
  295.        if( AES_Version >= 0x0320 )
  296.            graf_mouse( FLAT_HAND, 0L );
  297.  
  298.            if(( AES_Version >= 0x0330 )
  299.            && ( gl_ncolors > LWHITE ) )
  300.            XSelect( tree, Mslider );
  301.  
  302.            graf_mkstate( (int*)&mk.x, &oy, (int*)&mk.buttons, (int*)&mk.kstate );
  303.        do
  304.        {
  305.            graf_mkstate( (int*)&mk.x, (int*)&mk.y, (int*)&mk.buttons, (int*)&mk.kstate );
  306.        }while( mk.buttons && ( mk.y == oy ));
  307.  
  308.         if( mk.buttons && ( mk.y != oy ))
  309.        {
  310.            
  311.               sl_dragy( tree, Mbase, Mslider,
  312.                        max( Total - MAX_SLITS, 0 ), 0,
  313.                        &Cur_Slit, Draw_Slit );
  314.            }
  315.  
  316.        if(( AES_Version >= 0x0330 )
  317.             && ( gl_ncolors > LWHITE ) )
  318.            XDeselect( tree, Mslider );
  319.                              
  320.        MF_Restore();
  321.            return;          
  322.         }                     
  323.         
  324.         if( obj == Mbase )
  325.         {            
  326.            Graf_mkstate( &mk );
  327.            objc_offset( tree, Mslider, &ox, &oy );
  328.            ox = (( mk.y < oy ) ? ( -MAX_SLITS ) : ( MAX_SLITS ) );
  329.            sl_arrow( tree, Mbase, Mslider, -1, ox,
  330.                         max( Total - MAX_SLITS, 0 ), 0,
  331.                       &Cur_Slit, VERTICAL, Draw_Slit );
  332.            return;                                      
  333.         }                              
  334.  
  335.         /* CPX filename buttons */
  336.         if( ( obj >= Obj_Beg ) &&
  337.             ( obj <= Obj_End ) )
  338.         {           
  339.        if( clicks )
  340.        {
  341.        }
  342.        else
  343.            Do_Hot_Scroll( obj, hdptr, Active_Slit[ obj - First_Obj ],
  344.                            First_Obj, Total,
  345.                      Mbase, Mslider, &Cur_Slit,
  346.                      Active_Slit, Draw_Hot );
  347.        return;
  348.     }                      
  349.         Undo_Fnodes( hdptr, ( FON_PTR )NULL );
  350. }
  351.  
  352.  
  353.  
  354.  
  355. /* Undo_Fnodes()
  356.  *==========================================================================
  357.  * Deselects any Slits visible. Also, it goes down the slit ptr passed in,
  358.  * and undo's any changes made to the filename.
  359.  *
  360.  * IN:     FNODE *ptr:    Head Node pointer to the linked list.
  361.  *     BOOLEAN flag:    Defines which linked list to clear out.
  362.  */
  363. void
  364. Undo_Fnodes( FON_PTR ptr, FON_PTR flag )
  365. {
  366.     FON_PTR curptr;
  367.     int i;
  368.  
  369.     /* Here we restore whatever the previous state was */
  370.     if( !IsChanged( ptr ) )
  371.         return;
  372.  
  373.     curptr = ptr;
  374.     while( curptr )
  375.     {
  376.         AFLAG( curptr ) = SFLAG( curptr ) = FALSE;   
  377.         curptr = FNEXT( curptr );
  378.     }
  379.     
  380.     for( i = 0; i < MAX_SLITS; i++ )
  381.     {
  382.        if( IsSelected( First_Obj + i ) )
  383.           deselect( tree, First_Obj + i );
  384.     }
  385.  
  386.     if( IsActiveTree( ad_front ) && !flag )
  387.     {
  388.        if( !IsDisabled( FREMOVE ) )
  389.      ChangeButton( ad_front, FREMOVE, FALSE );
  390.        
  391.        if( !IsDisabled( FCONFIG ) )
  392.      ChangeButton( ad_front, FCONFIG, FALSE );
  393.     }
  394.  
  395.     if( IsActiveTree( ad_inactive ) && !flag )
  396.     {
  397.        if( !IsDisabled( IINSTALL ) )
  398.      ChangeButton( ad_inactive, IINSTALL, FALSE );
  399.        
  400.        if( !IsDisabled( ICONFIG ) )
  401.      ChangeButton( ad_inactive, ICONFIG, FALSE );
  402.  
  403.        CheckSelectAll( TRUE );
  404.     }
  405.  
  406.  
  407.  
  408.     /* This is the Point Size Dialog Box */
  409.     if( IsActiveTree( ad_points ) && !flag )
  410.     {
  411.        if( !IsDisabled( PNTDEL ) )
  412.      ChangeButton( ad_points, PNTDEL, FALSE );
  413.     }
  414.  
  415. }
  416.  
  417.  
  418.  
  419. /* Undo_Fnodes()
  420.  *==========================================================================
  421.  * Deselects any Slits visible. Also, it goes down the slit ptr passed in,
  422.  * and undo's any changes made to the filename.
  423.  *
  424.  * IN:     FNODE *ptr:    Head Node pointer to the linked list.
  425.  *     BOOLEAN flag:    Defines which linked list to clear out.
  426.  */
  427. void
  428. ClearFnodes( FON_PTR ptr )
  429. {
  430.     FON_PTR curptr;
  431.     int i;
  432.  
  433.     /* Here we restore whatever the previous state was */
  434.     if( !IsChanged( ptr ) )
  435.         return;
  436.  
  437.     curptr = ptr;
  438.     while( curptr )
  439.     {
  440.         AFLAG( curptr ) = SFLAG( curptr ) = FALSE;   
  441.         curptr = FNEXT( curptr );
  442.     }
  443.     
  444.     for( i = 0; i < MAX_SLITS; i++ )
  445.     {
  446.        if( IsSelected( First_Obj + i ) )
  447.           Deselect( First_Obj + i );
  448.     }
  449. }
  450.  
  451.  
  452.  
  453.  
  454. /* IsChanged()
  455.  *==========================================================================
  456.  * Used to see if any FNODES in the filename linked list has been 
  457.  * changed opposite from its aflag <=> sflag
  458.  * FNODE *ptr:    The head filename node for that linked list
  459.  *
  460.  * RETURN: TRUE  - YES
  461.  *       FALSE - NO
  462.  */
  463. BOOLEAN
  464. IsChanged( FON_PTR ptr )
  465. {
  466.    FON_PTR curptr;
  467.    BOOLEAN flag = FALSE;
  468.    
  469.    curptr = ptr;
  470.    while( curptr )
  471.    {
  472.        if( AFLAG( curptr ) )
  473.        {
  474.            flag = TRUE;
  475.            break;
  476.        }
  477.        curptr = FNEXT( curptr );   
  478.    }
  479.    return( flag );
  480. }
  481.  
  482.  
  483.  
  484.  
  485.  
  486.  
  487.  
  488. /*
  489.  *==========================================================================
  490.  * Linked List Handling
  491.  *==========================================================================
  492.  */
  493.  
  494.  
  495.  
  496. /* Assign_Slit()
  497.  *==========================================================================
  498.  *  Assigns the 6 slits visible an FNODE, where possible.
  499.  * IN: FNODE *ptr:    Start assigning with this node
  500.  *     FNODE *array[]:    A 5 slit pointer array.
  501.  */
  502. void
  503. Assign_Slit( FON_PTR ptr, FON_PTR array[] )
  504. {
  505.     int i;
  506.     FON_PTR curptr;
  507.     
  508.     curptr = ptr;
  509.     for( i = 0; i < MAX_SLITS; i++ )
  510.     {
  511.         array[ i ] = NULL;
  512.         Deselect( First_Obj + i );
  513.  
  514.     if( IsActiveTree( ad_points ) )
  515.           TedText( First_Obj + i ) = fblank2;
  516.  
  517.         if( IsActiveTree( ad_front ) || IsActiveTree( ad_inactive ) )
  518.           TedText( First_Obj + i ) = fblank;
  519.  
  520.         if( curptr )
  521.         {
  522.         /* if we are in point_size, and the point is zero,
  523.          * skip it...and continue with the next one.
  524.          */
  525.         if( IsActiveTree( ad_points ) )
  526.         {
  527.         if( !POINT_SIZE( curptr ) )
  528.            continue;
  529.             }
  530.  
  531.             array[i] = curptr;
  532.             TedText( First_Obj + i ) = FNAME( curptr );
  533.             
  534.         if( AFLAG( curptr ) )
  535.               Select( First_Obj + i );
  536.             curptr = FNEXT( curptr );    
  537.         }  
  538.     }
  539. }
  540.  
  541.  
  542.  
  543.  
  544. /* Draw_Slit()
  545.  *==========================================================================
  546.  * The Draw Slider Routine passed into the Active ( CPX ) slider routines.
  547.  */
  548. void
  549. Draw_Slit( void )
  550. {
  551.     slit_offset_adjust( hdptr, Cur_Slit, Active_Slit );
  552.     Blit_Slits( Old_Slit, Cur_Slit );
  553.     Old_Slit = Cur_Slit;
  554. }
  555.  
  556.  
  557. /* Draw_Hot()
  558.  *==========================================================================
  559.  * The Draw Slider Routine passed into the Active (CPX ) HOT slider
  560.  * Routines. This routine is used when we are doing ' hot' scrolling.
  561.  * Routines.
  562.  */
  563. void
  564. Draw_Hot( void )
  565. {
  566.     Hot_Scroll( hdptr, Cur_Slit, First_Obj, First_Obj + MAX_SLITS - 1 );
  567.     Draw_Slit();
  568. #if 0    
  569.     Evnt_timer( 50L );
  570. #endif    
  571. }
  572.  
  573.  
  574.  
  575. /* slit_offset_adjust()
  576.  *==========================================================================
  577.  * Assign the linked list to the slits. Used in conjuction with Assign_Slit.
  578.  * IN: FNODE *ptr:    The Head Pointer Node
  579.  *     int   value:    The Index (base 0 ) into the linked list
  580.  *     FNODE *array[]:    Text for the slider.
  581.  */
  582. void
  583. slit_offset_adjust( FON_PTR ptr, int value, FON_PTR array[] )
  584. {
  585.     FON_PTR curptr;
  586.     int   i;
  587.     
  588.     curptr = ptr;
  589.     
  590.      
  591.     for( i = 0; i < value; i++ )
  592.        curptr = FNEXT( curptr );
  593.     Assign_Slit( curptr, array );
  594. }
  595.  
  596.  
  597.  
  598.  
  599. /* blit_slits()
  600.  *==========================================================================
  601.  * Perform the blitting when the slits are scrolling.
  602.  * IN: BOOLEAN flag:    either Active or Inactive
  603.  *     int old_slit:    The previous slit
  604.  *     int new_slit:    The current slit to work on.
  605.  */
  606. void
  607. Blit_Slits( int old_slit, int new_slit )
  608. {
  609.     GRECT srcbase;
  610.     GRECT dstbase;
  611.     GRECT clip;
  612.     GRECT rect;
  613.     int   pxy[16];
  614.     GRECT clip2;
  615.                 
  616.     int   offset;
  617.     long  location = 0L;
  618.     int   dummy;
  619.     int   obj;
  620.     int   base;
  621.     
  622.     obj  = First_Obj;
  623.     base = Base_Obj;
  624.     clip = ObRect( base );
  625.     objc_offset( tree, obj, &clip.g_x, &clip.g_y );
  626.     clip2 = srcbase = dstbase = rect = clip;  
  627.     offset = new_slit - old_slit;
  628.                
  629.     if( !offset )            /* went nowhere fast...*/
  630.            return;
  631.            
  632.     if( !open_vwork())
  633.     {
  634.         form_alert( 1, alert18 );
  635.         return;
  636.     }
  637.  
  638.     rc_intersect( &desk, &clip2 );
  639.     if(  ( abs( offset )  <  MAX_SLITS ) &&
  640.          rc_equal( &clip2, &clip ) 
  641.       )
  642.     {
  643.        rect.g_h    = ( abs( offset ) * ObH( obj ) );
  644.        dstbase.g_h = srcbase.g_h = ( MAX_SLITS - abs( offset ) ) * ObH( obj );
  645.        if( offset > 0 )
  646.        {
  647.           objc_offset( tree, obj + abs( MAX_SLITS - offset ),
  648.                        &dummy, &rect.g_y );
  649.       objc_offset( tree, obj + abs( offset ), &dummy, &srcbase.g_y );
  650.        }
  651.        else
  652.       objc_offset( tree, obj + abs( offset ), &dummy, &dstbase.g_y );
  653.  
  654.        rc_intersect( &desk, &srcbase );
  655.        rc_intersect( &desk, &dstbase );
  656.        
  657.        rc_2xy( &srcbase, ( WORD *) &pxy[0] );
  658.        rc_2xy( &dstbase, ( WORD *)&pxy[4] );
  659.        rc_2xy( &clip, ( WORD *)&pxy[8] );
  660.        
  661.        vs_clip( vhandle, 1, &pxy[8] );
  662.  
  663.        graf_mouse( M_OFF, 0L );
  664.        Vsync();
  665.        vro_cpyfm( vhandle, 3, pxy, ( MFDB *)&location,
  666.                                    ( MFDB *)&location );
  667.        graf_mouse( M_ON, 0L );
  668.     }
  669.     else
  670.     {
  671.        rc_2xy( &clip, ( WORD *)&pxy[0] );
  672.        vs_clip( vhandle, 1, &pxy[0] );
  673.     }
  674.  
  675.     Vsync();
  676.     Objc_draw( tree, base, MAX_DEPTH, &rect );
  677.  
  678.     close_vwork();
  679. }
  680.  
  681.  
  682.  
  683.  
  684.  
  685.  
  686.  
  687. /*
  688.  *==========================================================================
  689.  * Hot and Cold Scroll Handling
  690.  *==========================================================================
  691.  */
  692.  
  693.  
  694.  
  695. /* Hot_Scroll() 
  696.  *=================================================================
  697.  * Object Scrolling Handler for Hot Scrolling Routines.
  698.  * Called ONLY by Draw_IHot() and Draw_AHot()
  699.  * The hot scrolling kicks in when the mouse is in ZONE 0 or ZONE 6.
  700.  * The zone boundaries are created by 'Make_Hot_Spots()'.
  701.  * IN:  FNODE *Xptr:    The Parent FNODE pointer to the linked list.
  702.  *      int cur_slit:    The current index into the linked list
  703.  *    int First_Obj:    Either A0 or I0 - the first clickable object
  704.  *    int End_Obj:    Either A5 or I5 - The last clickable object
  705.  *
  706.  * OUT: void
  707.  */
  708. void
  709. Hot_Scroll( FON_PTR Xptr, int cur_slit, int first_obj, int end_obj )
  710. {
  711.     FON_PTR curptr;
  712.     int   index;
  713.            
  714.     if( Xptr )
  715.     {
  716.      
  717.       if( hot_index == 0 )        /* ZONE 0 Hot Spot */
  718.       {
  719.         /* Scrolling around the TOP...*/
  720.         curptr = Find_Fnode( Xptr, cur_slit );
  721.         new_index = cur_slit;
  722.  
  723.        /* We must now compare the initial index ('findex') to
  724.         * our NEW index. If they are the same, we just draw it
  725.         * based on the flag.
  726.         */
  727.         if( new_index == findex )
  728.         {
  729.             if( AFLAG( Base_Node ) )
  730.                 Select( first_obj );
  731.         
  732.             else
  733.                 Deselect( first_obj );
  734.         }
  735.         
  736.         if( new_index < findex )
  737.         {
  738.          /* The New index is ABOVE the starting point.
  739.        * Therefore, we want to set the state to
  740.        * be the same as the 'Base_Node->aflag'
  741.        * The OBJECT is ALWAYS the first filename block
  742.        * while we are scrolling.
  743.        */
  744.            if( AFLAG( Base_Node ) )
  745.            {
  746.              /* Want them SELECTED
  747.               * So, if the node is deselected, SELECT IT
  748.           * else, leave it alone.
  749.               * NOTE: Don't update the 'sflag'
  750.               */
  751.          if( !AFLAG( curptr ) )
  752.                   AFLAG( curptr )^= TRUE;
  753.              Select( first_obj );    
  754.            }
  755.            else
  756.            {
  757.              /* Want it DESELECTED
  758.               * So, if the node is selected, DESELECT IT
  759.               * else, leave it alone.
  760.               * NOTE: Don't update the 'sflag'
  761.               */
  762.              if( AFLAG( curptr ) )
  763.                  AFLAG( curptr )^= TRUE;
  764.              Deselect( first_obj );     
  765.            }
  766.         }
  767.         
  768.     if( new_index > findex )           
  769.     {
  770.       /* The New index is BELOW the starting point.
  771.        * Therefore, we want to set the state of the object
  772.        * to its ORIGINAL state. This is the 'sflag'.
  773.        * The OBJECT is ALWAYS the first filename block
  774.        * while we are scrolling.
  775.        */
  776.        AFLAG( curptr ) = SFLAG( curptr );
  777.        if( AFLAG( curptr ) )
  778.            Select( first_obj );
  779.        else
  780.            Deselect( first_obj );
  781.     }
  782.       }
  783.       
  784.       
  785.       if( hot_index == ( MAX_SLITS + 1 ) )          /* ZONE 6 Hot Spot */
  786.       {
  787.          /* Scrolling around the Bottom */
  788.          curptr = Find_Fnode( Xptr, cur_slit + MAX_SLITS - 1);
  789.      index = Get_Findex( Xptr, curptr );
  790.      
  791.              new_index = index;
  792.  
  793.  
  794.              /* We must now compare the initial index ('findex') to
  795.               * our NEW index.
  796.               * If they are the same, we select/deselect it
  797.               * based on the status of Base_Node.
  798.               */
  799.               if( new_index == findex )
  800.               {
  801.                  if( AFLAG( Base_Node ) )
  802.                     Select( end_obj );
  803.                  else
  804.                     Deselect( end_obj );
  805.               }
  806.         
  807.               if( new_index < findex )
  808.               {
  809.                 /* The New index is ABOVE the starting point.
  810.                  * We want to RESTORE the original 'sflag' state.
  811.              * The OBJECT is ALWAYS the LAST filename block
  812.              * while we are scrolling.
  813.             */
  814.               AFLAG( curptr ) = SFLAG( curptr );
  815.               if( curptr->aflag )
  816.                    Select( end_obj );
  817.                  else
  818.                    Deselect( end_obj );
  819.               }
  820.               
  821.           if( new_index > findex )
  822.               {
  823.            /* The New index is BELOW the starting point.
  824.             * We want to set the state of the object to the
  825.             * same as the Base_Node.
  826.               */
  827.                  if( AFLAG( Base_Node ) )
  828.                   {
  829.                       /* Want them SELECTED
  830.                * So, if the node is deselected, SELECT IT
  831.                * else, leave it alone.
  832.                              * NOTE: Don't update the 'sflag'
  833.                    */
  834.                if( !AFLAG( curptr ) )
  835.                     AFLAG( curptr )^= TRUE;
  836.                Select( end_obj );    /* had I0 here */
  837.                   }
  838.                   else
  839.                   {
  840.                      /* Want it DESELECTED
  841.                   * So, if the node is selected, DESELECT IT
  842.                       * else, leave it alone.
  843.                        * NOTE: Don't update the 'sflag'
  844.                       */
  845.                       if( AFLAG( curptr ) )
  846.                          AFLAG( curptr )^= TRUE;
  847.                       Deselect( end_obj );     /* had I0 here */
  848.                   }
  849.           }
  850.  
  851.       }               /* hot_index == 6 */
  852.     }
  853.  
  854.  
  855. }
  856.  
  857.  
  858.  
  859.  
  860.  
  861.  
  862. /* Make_Hot_Spots()
  863.  *==========================================================================
  864.  * Create the # Hot spot rectangles required for scrolling through the
  865.  * filenames.  They are in this order:
  866.  *
  867.  *        ______________________
  868.  *        |                    |        ZONE 0 ( Above )
  869.  *        |                    |
  870.  *        +--------------------+
  871.  *        |                    |        ZONE 1 ( LINE0 )
  872.  *        |                    |
  873.  *        +--------------------+
  874.  *        |                    |        ZONE 2 ( LINE1 )
  875.  *        |                    |
  876.  *        +--------------------+
  877.  *        |                    |        ZONE 3 ( LINE2 )
  878.  *        |                    |
  879.  *        +--------------------+
  880.  *        |                    |        ZONE 4 ( LINE3 )
  881.  *        |                    |
  882.  *        +--------------------+
  883.  *        |                    |        ZONE 5 ( LINE4 )
  884.  *        |                    |
  885.  *        +--------------------+
  886.  *        |                    |        ZONE 6 ( LINE5 )
  887.  *        |                    |
  888.  *        +--------------------+
  889.  *        |             |        ZONE 7 ( BELOW )
  890.  *        |             |
  891.  *        ----------------------
  892.  *
  893.  * NOTE: The widths of the zones are the width of the screen.
  894.  * IN: int top_object:    LINE0
  895.  */
  896. void
  897. Make_Hot_Spots( int top_object )
  898. {
  899.    int i;
  900.    int obj;
  901.    GRECT rect;
  902.       
  903.    for( i = 1; i <= MAX_SLITS; i++ )
  904.    {
  905.       obj = top_object + i - 1;
  906.       hot_spot[ i ] = ObRect( obj );
  907.       objc_offset( tree, obj, &hot_spot[i].g_x, &hot_spot[i].g_y );
  908.       hot_spot[ i ].g_w = desk.g_w;
  909.       hot_spot[ i ].g_x = desk.g_x;
  910.    }
  911.    rect = desk;
  912.    rect.g_y = 0;
  913.    rect.g_h = desk.g_y + desk.g_h;
  914.    
  915.    hot_spot[0] = hot_spot[ MAX_SLITS + 1 ] = rect;
  916.    hot_spot[ 0 ].g_h = hot_spot[ 1 ].g_y;
  917.    hot_spot[ MAX_SLITS + 1 ].g_y = hot_spot[ MAX_SLITS ].g_y + hot_spot[ MAX_SLITS ].g_h; 
  918.    hot_spot[ MAX_SLITS + 1 ].g_h = rect.g_h - hot_spot[ MAX_SLITS + 1 ].g_y + 1;
  919.  
  920.    /* Now, adjust the rectangles clipped to the desktop */   
  921.    for( i = 0; i < ( MAX_SLITS + 2 ); i++ )
  922.       rc_intersect( &rect, &hot_spot[ i ] );
  923. }
  924.  
  925.  
  926.  
  927.  
  928. /* Get_Findex()
  929.  *==========================================================================
  930.  * Given the Parent FNODE pointer AND the FNODE pointer in question,
  931.  * find its index into the linked list ( zero based ).
  932.  * IN: FNODE *tptr:    The Parent FNODE pointer
  933.  *     FNODE *ptr:    The FNODE pointer we want the index for.
  934.  *
  935.  * OUT: int:    The index into the linked list ( 0 based ) to the FNODE *ptr
  936.  */
  937. int
  938. Get_Findex( FON_PTR tptr, FON_PTR ptr )
  939. {
  940.     FON_PTR curptr;
  941.     int   count = 0;
  942.     
  943.     curptr = tptr;
  944.     while( curptr )
  945.     {
  946.          if( curptr == ptr )
  947.               break;
  948.          count++;
  949.          curptr = FNEXT( curptr );
  950.     }
  951.     return( count );
  952. }
  953.  
  954.  
  955.  
  956. /* Get_Hot_Index()
  957.  *==========================================================================
  958.  * Get the 'hot_index' INDEX INTO the hot_spot array to tell us
  959.  * which rectangle we ended up in for our filename scrolling.
  960.  * Returns the OLD hot_index in d0 and the NEW hot_index in A0.
  961.  * IN:    int *hot_index:       Our previus ZONE that we were in. 
  962.  *               Upon exit, contains the NEW ZONE that we are in.
  963.  * OUT: int:           Returns the OLD ZONE that we were in.
  964.  */
  965. int
  966. Get_Hot_Index( int *hot_index )
  967. {
  968.     int   index = 0;
  969.     int   cold_index;
  970.     MRETS mk;
  971.    
  972.     cold_index = *hot_index;
  973.      
  974.     Graf_mkstate( &mk );
  975.     while( !xy_inrect( mk.x, mk.y, &hot_spot[ index++ ] ));                     
  976.     index -= 1;
  977.  
  978.     *hot_index = index;    
  979.     return( cold_index );
  980. }
  981.  
  982.  
  983.  
  984.  
  985.  
  986. /* Find_Fnode()
  987.  *==========================================================================
  988.  * Given the Parent FNODE pointer ( filename node ) and the index (base 0 )
  989.  * into the linked list, return the FNODE pointer to that index.
  990.  * Note that we will return the end pointer if index exceeds the number
  991.  * of nodes.
  992.  * IN:    FNODE *ptr:    The parent FNODE pointer to the list.
  993.  *    int index;    The INDEX into the linked list ( 0 based )
  994.  *
  995.  * OUT: FNODE *ptr:    Return the pointer to the node indexed in.
  996.  */
  997. FON_PTR
  998. Find_Fnode( FON_PTR ptr, int index )
  999. {
  1000.     FON_PTR curptr;
  1001.     int count = 0;
  1002.     
  1003.     curptr = ptr;
  1004.     while( curptr && ( count != index ) )
  1005.     {
  1006.      count++;  
  1007.         curptr = FNEXT( curptr );
  1008.     }           
  1009.  
  1010.     return( curptr );   
  1011. }
  1012.  
  1013.  
  1014.  
  1015.  
  1016.  
  1017. /* Old_Index_Handler()
  1018.  *==========================================================================
  1019.  * 1) Selects/Deselects a filename object for the MOVER/RENAMER.
  1020.  * 2) Sets the FNODE flag of the old_index either to SELECT or DESELECT
  1021.  * NOTE: This routine basically cleans up AFTER 'new_index' and
  1022.  *      follows it around.
  1023.  * 
  1024.  * IN:     int old_index:         OLD index object INTO linked list 
  1025.  *    int new_index:         NEW index object INTO linked list 
  1026.  *    int findex:         index object INTO linked list that 
  1027.  *                 started all this scrolling thing... 
  1028.  *    FNODE *Top_Node:     STARTING node of linked list         
  1029.  *      FNODE *Base_Node:     The findex NODE pointer
  1030.  *    int Above_Obj:         rcs object when old_index < findex    
  1031.  *    int Below_Obj:         rcs object when old_index > findex 
  1032.  */
  1033. void
  1034. Old_Index_Handler( int old_index, int new_index, int findex,
  1035.            FON_PTR Top_Node, FON_PTR Base_Node,
  1036.            int Above_Obj, int Below_Obj )
  1037. {
  1038.    FON_PTR Old_Node;            /* FNODE pointer of 'old_index'  */
  1039.    
  1040.    /* if the old_index is the same as 'findex', or
  1041.     * 'old_index' is the same as 'new_index',
  1042.     * then skip this routine.
  1043.     */
  1044.    if(( old_index != findex ) && ( old_index != new_index ) )                   
  1045.    {
  1046.  
  1047.       /* Get the NODE for the 'old_index'.  Find_Fnode() will always
  1048.        * return a node regardless. 'Top_Node' contains at least 
  1049.        * ONE node, otherwise, 'Old_Index_Handler would never have been
  1050.        * called.
  1051.        */
  1052.        Old_Node = Find_Fnode( Top_Node, old_index );
  1053.  
  1054.  
  1055.       /* CODE to Handle 'old_index' ABOVE 'findex' */
  1056.       if( old_index < findex )
  1057.       {
  1058.          /* Check if we are ABOVE or BELOW the 'new_index'
  1059.           *==================================================
  1060.           * CODE ONLY for 'old_index' being ABOVE 'new_index'
  1061.           * AND ABOVE 'findex'.
  1062.           * MEANING: the 'new_index' moved DOWNWARDS.
  1063.           *==================================================
  1064.           * For 'old_index' being ABOVE 'findex' BUT
  1065.           * BELOW 'new_index'.
  1066.           * MEANING: 'new_index' moved UPWARDS!
  1067.           * HOWEVER: INSPECTION reveals that 'old_index'
  1068.           *          handling is not required for that case.
  1069.           */
  1070.       if( old_index < new_index )
  1071.           {
  1072.              /* We must RESTORE the 'Old_Node' to its
  1073.               * previous state, IF the conditions 
  1074.               * are met. Otherwise, do not touch anything.
  1075.               */
  1076.              if( AFLAG( Base_Node ) )
  1077.              {
  1078.                  if( !SFLAG( Old_Node ) )
  1079.                  {
  1080.                      AFLAG( Old_Node ) = SFLAG( Old_Node );
  1081.                      deselect( tree, Above_Obj );
  1082.                  }
  1083.              }
  1084.              else
  1085.              {
  1086.                  if( SFLAG( Old_Node ) )
  1087.                  {
  1088.                      AFLAG( Old_Node ) = SFLAG( Old_Node );
  1089.                      select( tree, Above_Obj );
  1090.                  }
  1091.              }
  1092.           }
  1093.                                   
  1094.       }                /* End of ( old_index < findex */
  1095.                                
  1096.  
  1097.  
  1098.       /* CODE to Handle 'old_index' BELOW 'findex' */    
  1099.       if( old_index > findex )
  1100.       {
  1101.      /* Check if we are ABOVE or BELOW the 'new_index'
  1102.           *==================================================
  1103.           * CODE ONLY for 'old_index' being BELOW 'new_index'
  1104.           * AND BELOW 'findex'.
  1105.           * MEANING: the 'new_index' moved UPWARDS.
  1106.           *==================================================
  1107.           * For 'old_index' being BELOW 'findex' AND
  1108.           * ABOVE 'new_index'...'new_index' moved 'DOWNWARDS'.
  1109.           * HOWEVER: INSPECTION reveals that 'old_index'
  1110.           *         handling is not required for that case.
  1111.           */
  1112.           if( old_index > new_index )
  1113.           {
  1114.              /* Restore the 'old_node' to its previous state
  1115.               * if the below conditions are met. Otherwise
  1116.               * do not touch anything...
  1117.               */
  1118.              if( AFLAG( Base_Node ) )
  1119.              {
  1120.                  if( !SFLAG( Old_Node ) )
  1121.                  {
  1122.                     AFLAG( Old_Node ) = SFLAG( Old_Node );
  1123.                     deselect( tree, Below_Obj );
  1124.                  }
  1125.              }
  1126.              else
  1127.              {
  1128.                  if( SFLAG( Old_Node ) )
  1129.                  {
  1130.                    AFLAG( Old_Node ) = SFLAG( Old_Node );
  1131.                    select( tree, Below_Obj );
  1132.                  }
  1133.              }
  1134.       }
  1135.        }                 
  1136.     }            /* If( ( old_index != new_index ) && ( old_index != findex ) ) */
  1137. }
  1138.  
  1139.  
  1140.  
  1141.  
  1142.  
  1143.  
  1144. /* New_Index_Handler()
  1145.  *==========================================================================
  1146.  * 1) Selects/Deselects a filename object for the MOVER/RENAMER.
  1147.  * 2) Sets the FNODE flag of the new_index either to SELECT or DESELECT
  1148.  * NOTE: This deals with 'new_index' which is followed by 'old_index'
  1149.  * 
  1150.  * IN:     int old_index:         OLD index object INTO linked list 
  1151.  *    int new_index:         NEW index object INTO linked list 
  1152.  *    int findex:         index object INTO linked list that 
  1153.  *                 started all this scrolling thing... 
  1154.  *    FNODE *Top_Node:     STARTING node of linked list         
  1155.  *    FNODE *Base_Node:     FINDEX node in LINKED list         
  1156.  *    int Above_Obj:         rcs object when old_index < findex    
  1157.  *    int Below_Obj:         rcs object when old_index > findex 
  1158.  */
  1159. void
  1160. New_Index_Handler( int old_index, int new_index, int findex,
  1161.            FON_PTR Top_Node, FON_PTR Base_Node,
  1162.            int Above_Obj, int Below_Obj )
  1163. {
  1164.    FON_PTR New_Node;            /* FNODE pointer of 'old_index'  */
  1165.  
  1166.    /* If the 'new_index' is the same as 'old_index' or
  1167.     * it is the same as 'findex', we skip this routine entirely.
  1168.     */                           
  1169.   if( ( new_index != old_index ) && ( new_index != findex ) )
  1170.   {
  1171.       /* Get the FNODE pointer based on the 'new_index' index.
  1172.        * NOTE: We will always have a node, otherwise this
  1173.        *       routine will never have been called.
  1174.        */
  1175.       New_Node = Find_Fnode( Top_Node, new_index );
  1176.  
  1177.       /* We must now decide whether to select, deselect or
  1178.        * leave the node flag alone depending upon the 
  1179.        * position of findex, old_index and new_index.
  1180.        * Depending upon the state of 'Base_Node', we will
  1181.        * either Select, Deselect or skip the node.
  1182.        */                           
  1183.  
  1184.      /* CODE where 'new_index' < 'findex'
  1185.       * MEANING: We are ABOVE findex.
  1186.       */                               
  1187.      if( new_index < findex )
  1188.      {
  1189.          /* Check if we are ABOVE or BELOW the 'old_index'
  1190.           *===============================================
  1191.           * CODE ONLY for 'new_index' ABOVE 'old_index'
  1192.           * NOTE: We are MOVING UPWARDS.
  1193.           * HERE, we save the 'aflag' state to 'sflag'
  1194.           * and then toggle 'aflag'.
  1195.           * We THEN, REDRAW the OBJECT that the node
  1196.           * was in.
  1197.           *===============================================
  1198.           * NOTE: For the case where new_index > old_index.
  1199.           * This is where 'new_index' is BELOW 'old_index'
  1200.           * We are MOVING DOWNWARDS.
  1201.           * HOWEVER, initial estimates show that we can
  1202.           * ignore this case.
  1203.           */
  1204.          if( new_index < old_index )
  1205.          {
  1206.         if( AFLAG( Base_Node ) )
  1207.             {
  1208.                 /* The Base_Node wants SELECTED.
  1209.                  * So, if our 'New_Node' is Deselected, SELECT IT!
  1210.                  * by backing up to 'sflag' and toggling 'aflag'.
  1211.                  * If we have already SELECTED it, don't do anything.
  1212.                  */
  1213.                 if( !AFLAG( New_Node ) )
  1214.                 {
  1215.                    SFLAG( New_Node ) = AFLAG( New_Node );
  1216.                    AFLAG( New_Node )^= TRUE;
  1217.                    select( tree, Above_Obj );
  1218.                 }
  1219.             }
  1220.             else
  1221.             {
  1222.                 /* The Base_Node wants DESELECTED!
  1223.                  * So, if our 'New_Node' is Selected, DESELECT IT!
  1224.                  * by backing up to 'sflag' and toggling 'aflag'.
  1225.                  * If we have already DESELECTED it, don't do anything.
  1226.                  */
  1227.                 if( AFLAG( New_Node ) )
  1228.                 {
  1229.                     SFLAG( New_Node ) = AFLAG( New_Node );
  1230.                     AFLAG( New_Node )^= TRUE;
  1231.                     deselect( tree, Above_Obj );
  1232.                 }
  1233.             }            
  1234.          }        /* end of if( new_index < old_index ) */
  1235.                                   
  1236.      }
  1237.                                
  1238.  
  1239.     /* CODE where 'new_index' > 'findex'.
  1240.      * MEANIN: We are BELOW 'findex'.
  1241.      */                               
  1242.     if( new_index > findex )
  1243.     {
  1244.         /* NOTE: Initial analysis shows that the case
  1245.          * new_index < old_index can be ignored.
  1246.          */
  1247.         if( new_index > old_index )
  1248.         {
  1249.            /* We are BELOW findex AND BELOW old_index...
  1250.             * meaning, we have moved DOWNWARDS to the new_index.
  1251.             */
  1252.            if( AFLAG( Base_Node ) )
  1253.            {
  1254.               /* The BASE wants SELECTED!
  1255.                * If we are DESELECTED, SELECT IT!
  1256.                * Update 'sflag' and toggle 'aflag'
  1257.                * If ALREADY SELECTED, SKIP! 
  1258.                */
  1259.               if( !AFLAG( New_Node ) )
  1260.               {
  1261.                  SFLAG( New_Node ) = AFLAG( New_Node );
  1262.                  AFLAG( New_Node ) ^= TRUE;
  1263.                  select( tree, Below_Obj );
  1264.               }
  1265.            }
  1266.            else
  1267.            {
  1268.               /* The BASE wants DESELECTED!
  1269.                * If we are SELECTED, DESELECT IT!
  1270.                * Update 'sflag' and toggle 'aflag'
  1271.                * If ALREADY DESELECTED, SKIP!
  1272.                */
  1273.               if( AFLAG( New_Node ) )
  1274.               {
  1275.                   SFLAG( New_Node ) = AFLAG( New_Node );
  1276.                   AFLAG( New_Node )^= TRUE;
  1277.                   deselect( tree, Below_Obj );
  1278.               }
  1279.            }  
  1280.       }
  1281.    }                    
  1282.   }  /* End of if( old_index != new_index etc..*/
  1283. }
  1284.  
  1285.  
  1286.  
  1287.  
  1288.  
  1289.  
  1290.  
  1291.  
  1292. /* Do_Hot_Scroll()
  1293.  *==========================================================================
  1294.  * Perform THE HOT Scrolling by dragging the mouse around.
  1295.  * Called when LINE0 - LINE5 is clicked on.
  1296.  * 
  1297.  * int obj:        The Initial Object selected
  1298.  * int Top_Obj:        The Top Object selectable: A0 or I0
  1299.  * FNODE *Top_Node:    The Head Pointer Node of Linked List
  1300.  * FNODE *Base_Node:    The Node Pointer of the object selected.
  1301.  * int  Total:        Total Number of objects to scroll...
  1302.  *
  1303.  */
  1304. void
  1305. Do_Hot_Scroll( int obj, FON_PTR Top_Node, FON_PTR base_node,
  1306.            int Top_Obj, int Total,
  1307.            int Xbase, int Xslider, int *cur_slit,
  1308.            FON_PTR Slit_Array[],  void (*foo)() )
  1309. {
  1310.      MRETS mk;
  1311.      
  1312.      int  sindex;            /* index into Slit Arrays */
  1313.      int  bstate;            /* Button state */
  1314.  
  1315.      int   cold_index;            /* shadow for hot_index */
  1316.      int   old_index;            /* Old index into linked list ( zero based ) */
  1317.      int   temp_index;
  1318.      FON_PTR New_Node;            /* The Node pointer to the new_index slot */
  1319.      int   ox;
  1320.      int  dir, index;
  1321.      BOOLEAN Skip_Flag = FALSE;
  1322.      BOOLEAN Scroll_Exit = FALSE;
  1323.           
  1324.      Base_Node = base_node;        /* Base_Node is Global and needs updating */
  1325.  
  1326.      sindex = obj - Top_Obj;
  1327.      
  1328.      Graf_mkstate( &mk );    
  1329.  
  1330.      /* If the person is holding down the shift key, add
  1331.       * another item. OTHERWISE, clear all of them.
  1332.       * HOWEVER, if this is the printer dialogbox, skip it! 
  1333.       */
  1334.      if( !( mk.kstate && K_LSHIFT ) )
  1335.              Undo_Fnodes( Top_Node, Base_Node );
  1336.     
  1337.      if( Top_Node && Base_Node )
  1338.      {
  1339.          AFLAG( Base_Node )^= TRUE;        /* <=====   NOTE: there might be a problem here */
  1340.          SFLAG( Base_Node ) = AFLAG( Base_Node );   /* Especially when shift key is supposed to be down*/
  1341.          if( AFLAG( Base_Node ) )
  1342.             select( tree, obj );
  1343.          else
  1344.             deselect( tree, obj );
  1345.       
  1346.          cold_index = hot_index = sindex + 1;
  1347.          findex = Get_Findex( Top_Node, Base_Node );
  1348.          old_index = new_index = findex;
  1349.          
  1350.          New_Node = Top_Node;
  1351.          while( New_Node )
  1352.          {
  1353.              SFLAG( New_Node ) = AFLAG( New_Node );
  1354.              New_Node = FNEXT( New_Node );
  1355.          }
  1356.          New_Node = NULL;
  1357.      }
  1358.     
  1359.     
  1360.      /* ------------------------------------------------------------
  1361.       * Enable or Disable the REMOVe and CONFIG buttons on
  1362.       * 2 dialog boxes...
  1363.       */
  1364.       
  1365.       
  1366.       /* This is the front dialog box - installed fonts */
  1367.       CheckHotFront( Top_Node );
  1368.  
  1369.       /* This is the available fonts dialog box..*/
  1370.       CheckHotAvailable( Top_Node );
  1371.      
  1372.       /* This is the Point Size dialog box */
  1373.       CheckHotPoints( Top_Node );
  1374.  
  1375.      Make_Hot_Spots( Top_Obj );
  1376.      do
  1377.      {
  1378.        /* Skip this whole mess if there isn't a Header Pointer or
  1379.         * a pointer where we clicked on.
  1380.         */
  1381.      if( Top_Node && Base_Node )
  1382.      {
  1383.          /* We now will look for the exit condition ( Going OUT )
  1384.           * or an up button, whichever occurs first.
  1385.           * Returns ZERO if button event occurred.
  1386.           */
  1387.          if( !Scroll_Exit ) 
  1388.               bstate = rub_wait( &hot_spot[ hot_index ], 1, 0 );
  1389.          else
  1390.               bstate = FALSE;
  1391.                    
  1392.          if( !bstate )
  1393.          {
  1394.              /* Find out which hot_spot rectangle that we are in. */
  1395.              cold_index = Get_Hot_Index( &hot_index );
  1396.              
  1397.              /* If we have ended up in the SAME 'hot_index' slit, 
  1398.               * then we have gone nowhere. Therefore, skip
  1399.               * any scrolling.
  1400.               */
  1401.              
  1402.              Scroll_Exit = Skip_Flag = FALSE;
  1403.              if( hot_index != cold_index )
  1404.              {
  1405.             /*************************************************
  1406.             * Hot_Index SCROLLING of filenames
  1407.             * We have ended up within the filename slits.
  1408.             *************************************************/
  1409.  
  1410.             /* There are several cases possible only
  1411.              *            START         END
  1412.              *          Cold_Index          Hot_Index
  1413.              * CASE 0:      0 | 7        0 | 7
  1414.              * CASE 1:      0 | 7        1 - 6          
  1415.              * CASE 2:      1-6            0 | 7
  1416.              * case 3:        1-6            1 - 6
  1417.              * 
  1418.              * We are going to have to clean up form cold to hot_index
  1419.              * in turn since they might not necessarily be adjacent.
  1420.              */
  1421.  
  1422.             dir = 0;
  1423.             dir = (( hot_index < cold_index ) ? ( -1 ) : ( dir ) );
  1424.             dir = (( hot_index > cold_index ) ? ( 1 ) : ( dir ) );
  1425.             index = cold_index + dir;
  1426.  
  1427.             if(( cold_index == 0 ) || ( cold_index == ( MAX_SLITS + 1 )))
  1428.             {
  1429.                 old_index = (( cold_index == 0 ) ? ( max( new_index - 1 , 0 ) ) : ( min( new_index + 1, Total - 1 )) );
  1430.                 if( old_index != new_index )
  1431.                 {
  1432.                  New_Node = Slit_Array[ index - 1 ];
  1433.                  if( New_Node )
  1434.                  {
  1435.                  new_index = Get_Findex( Top_Node, New_Node );
  1436.  
  1437.                      New_Index_Handler( old_index, new_index, findex,
  1438.                                    Top_Node, Base_Node,
  1439.                             ( index - 1 ) + Top_Obj,
  1440.                             ( index - 1 ) + Top_Obj );
  1441.                   }         
  1442.                 }
  1443.                 old_index = new_index;
  1444.                              
  1445.                 if( index != hot_index )
  1446.                     index += dir;
  1447.                 else
  1448.                     Skip_Flag = TRUE;       
  1449.                                      
  1450.                 while( index != hot_index )
  1451.                 {
  1452.                  Hot_Old_New_Update( index, Top_Node,
  1453.                                  old_index, findex, 
  1454.                                       Top_Obj, Slit_Array );
  1455.                                 
  1456.                      index += dir;
  1457.                      old_index = new_index;    /* warning: new_index is global */
  1458.                      Skip_Flag = FALSE;    
  1459.                 }   
  1460.             
  1461.             } /* End of if(( cold_index == 0 ) || ( cold_index == ( MAX_INDEX + 1 )) */
  1462.  
  1463.             if(( cold_index > 0 ) && ( cold_index <= MAX_SLITS ))
  1464.             {
  1465.                 while( index != hot_index )
  1466.                 {
  1467.                 Hot_Old_New_Update( index, Top_Node,
  1468.                                 old_index, findex, 
  1469.                                      Top_Obj, Slit_Array );
  1470.                         
  1471.                     index += dir;
  1472.                     old_index = new_index;    /* warning: new_index is global */
  1473.                  }
  1474.             
  1475.             }    /* End of if(( cold_index > 0 ) && ( cold_index <= MAX_INDEX ))*/
  1476.  
  1477.                   if(( ( hot_index > 0 ) && ( hot_index < ( MAX_SLITS + 1 ) ) ) && !Skip_Flag )
  1478.             {
  1479.             Hot_Old_New_Update( hot_index, Top_Node,
  1480.                                  old_index, findex, 
  1481.                                  Top_Obj, Slit_Array );
  1482.                    }                                               
  1483.             
  1484.  
  1485.             if( ( hot_index == 0 ) || ( hot_index == ( MAX_SLITS + 1 ) ) )
  1486.             {
  1487.                   /* We have ENTERED the box ABOVE or BELOW
  1488.                    * the Object area, therefore, SCROLL, if possible 
  1489.                    *
  1490.                    * hot_index == 0 or hot_index == 6 ( outside obj boundaries )
  1491.                    */
  1492.                            
  1493.                    /* need to update the old_index HERE before we enter the scroll */
  1494.                    temp_index = (( hot_index == 0 ) ? ( new_index - 1 ) : ( new_index + 1 ) );
  1495.                Old_Index_Handler( old_index, temp_index, findex,
  1496.                                   Top_Node, Base_Node,
  1497.                                   ( hot_index - 2 ) + Top_Obj,
  1498.                            hot_index + Top_Obj );
  1499.                ox = ( ( hot_index == 0 ) ? ( -1 ) : ( 1 ) );
  1500.                    Hot_Slide( tree, Xbase, Xslider, -1,
  1501.                              ox, max( Total - MAX_SLITS, 0 ), 0,
  1502.                              cur_slit, VERTICAL, &hot_spot[ hot_index ],
  1503.                              foo );
  1504.                                      
  1505.             /* Update the Hot_Index flag to see where we really are...
  1506.              * It SHOULD be either hot_index 1 or 5
  1507.              *
  1508.              * Need to figure out why slot 0 and 4 do not select or
  1509.              * deselect after a slide like this.
  1510.              *
  1511.              */
  1512.              Scroll_Exit = TRUE;
  1513.             }
  1514.              
  1515.              /* Update the old_index and the NEW index...*/
  1516.             old_index = new_index;
  1517.  
  1518.              }              /* End of 'if( hot_index != cold_index )' */
  1519.          }                /* End of 'if( !bstate )'          */
  1520.      }    
  1521.     Graf_mkstate( &mk );
  1522.      }while( mk.buttons != 0 );
  1523. }
  1524.  
  1525.  
  1526.  
  1527.  
  1528.  
  1529. /* Hot_Old_New_Update()
  1530.  *==========================================================================
  1531.  * Combines the Updating of the 'old_index' and the 'new_index' into
  1532.  * one routine.
  1533.  *
  1534.  * IN:     int index:        The 'hot ZONE index'
  1535.  *    FNODE *Top_Node:    The Parent Node pointer to the list
  1536.  *    int old_index:        The 'old_index' into the linked list
  1537.  *    int findex:        The index to the fnode which we
  1538.  *                clicked on to start the scrolling.
  1539.  *    int Top_Obj:        Either A0 | I0
  1540.  *    FNODE *Slit_Array[]    The array (either for CPX or CPZ )
  1541.  *                that contains a pointer to the
  1542.  *                FNODE in that slit.
  1543.  */
  1544. FON_PTR
  1545. Hot_Old_New_Update( int index, FON_PTR Top_Node,
  1546.              int old_index, int findex,
  1547.              int Top_Obj, FON_PTR Slit_Array[] )
  1548. {
  1549.    FON_PTR New_Node = NULL;
  1550.  
  1551.     /**********************************************
  1552.      * We have ENTERED a NEW object area.
  1553.      * Get the FNODE and find out what the NEW 
  1554.      * 'new_index' for that node is. If there is
  1555.      * NO NODE, we SKIP any scrolling.
  1556.      **********************************************/
  1557.     New_Node = Slit_Array[ index - 1 ];
  1558.     if( New_Node )
  1559.     {
  1560.          new_index = Get_Findex( Top_Node, New_Node );
  1561.  
  1562.          Old_Index_Handler( old_index, new_index, findex,
  1563.                             Top_Node, Base_Node,
  1564.                             ( index - 2 ) + Top_Obj,
  1565.                     index + Top_Obj );
  1566.  
  1567.          New_Index_Handler( old_index, new_index, findex,
  1568.                   Top_Node, Base_Node,
  1569.                 ( index - 1 ) + Top_Obj,
  1570.                 ( index - 1 ) + Top_Obj );
  1571.     }
  1572.     return( New_Node );
  1573. }
  1574.  
  1575.  
  1576.  
  1577. int
  1578. rub_wait( GRECT *obj, int dir, int state )
  1579. {
  1580.     int which, kr;
  1581.     int mb, ks, br;
  1582.     int mx, my;
  1583.     
  1584.     wind_update( BEG_MCTRL );
  1585.     which = evnt_multi( MU_BUTTON | MU_M1 , 0x01, 0x01, state,
  1586.     dir, obj->g_x, obj->g_y, obj->g_w, obj->g_h,
  1587.     0,0,0,0,0,
  1588.     0L,
  1589.     0,0,
  1590.     &mx, &my, &mb, &ks, &kr, &br);
  1591.     wind_update( END_MCTRL );
  1592.     return( which & MU_BUTTON );
  1593. }
  1594.  
  1595.  
  1596.  
  1597.  
  1598.  
  1599. /* Hot_Slide()
  1600.  *==========================================================================
  1601.  * Used EXCLUSIVELY by the HOT SCrolling routines in MOVER.C
  1602.  * This routine was needed because the existing routines couldn't
  1603.  * handle it.
  1604.  *
  1605.  * IN:    OBJECT *tree:        The object tree
  1606.  *    int base:        The base of the slider
  1607.  *    int slider:        The slider object.
  1608.  *    int obj:        The object clicked on ( -1 if none )
  1609.  *    int inc:        increment (+/- # )
  1610.  *    int min:        minimum value
  1611.  *    int max:        maximum value
  1612.  *    int *numvar:        current value
  1613.  *    int direction:        VERTICAL | HORIZONTAL
  1614.  *    GRECT *rect:        Rectangle for our hot spot. If we exit the
  1615.  *                rectangle, we exit this routine also.
  1616.  *    void (*foo)():        The custom slider draw routine.
  1617.  */
  1618. void
  1619. Hot_Slide( OBJECT *tree, int base, int slider, int obj,
  1620.            int inc, int min, int max, int *numvar,
  1621.            int direction, GRECT *rect, void (*foo)() )
  1622. {
  1623.     MRETS mk;
  1624.     int   newvalue, oldvalue;
  1625.     GRECT slidrect;
  1626.  
  1627.     slidrect = ObRect( slider );
  1628.     objc_offset( tree, slider, &slidrect.g_x, &slidrect.g_y );
  1629.     /* account for outlines */
  1630.     slidrect.g_x -= 3;
  1631.     slidrect.g_y -= 3;
  1632.     slidrect.g_w += 6;
  1633.     slidrect.g_h += 6;
  1634.  
  1635.     if( obj > 0 )
  1636.     XSelect( tree, obj );
  1637.  
  1638.     oldvalue = *numvar;
  1639.     do {
  1640.     newvalue = *numvar + inc;
  1641.  
  1642.     if( max > min )
  1643.     {
  1644.         if( newvalue < min ) newvalue = min;
  1645.         else if( newvalue > max ) newvalue = max;
  1646.     }
  1647.     else
  1648.     {
  1649.         if( newvalue > min ) newvalue = min;
  1650.         else if( newvalue < max ) newvalue = max;
  1651.     }
  1652.  
  1653.     /* if in bounds, change the slider thumb */
  1654.     if( newvalue != oldvalue ) {
  1655.         oldvalue = newvalue;
  1656.         *numvar = newvalue;
  1657.         if( direction == VERTICAL )
  1658.           sl_y( tree, base, slider, newvalue, min, max, foo );
  1659.         /* undraw old */
  1660.         Objc_draw( tree, base, 3 , &slidrect ); /* was 0 */
  1661.         /* draw new */
  1662.         objc_offset( tree, slider, &slidrect.g_x, &slidrect.g_y );
  1663.             slidrect.g_x -= 3;
  1664.             slidrect.g_y -= 3;
  1665.         Objc_draw( tree, slider, 3 , &slidrect );
  1666.         
  1667.         }
  1668.     Graf_mkstate( &mk );
  1669.     } while( ( mk.buttons != 0 ) && ( xy_inrect( mk.x, mk.y, rect )));
  1670.  
  1671.     if( obj > 0 )
  1672.     XDeselect( tree, obj );
  1673.     Objc_draw( tree, base, MAX_DEPTH, &slidrect );
  1674. }
  1675.  
  1676.  
  1677. /* FindNumSelected()
  1678.  *==========================================================================
  1679.  */
  1680. int
  1681. FindNumSelected( FON_PTR ptr )
  1682. {
  1683.    FON_PTR curptr;
  1684.    int     count;
  1685.    
  1686.    count  = 0;
  1687.    curptr = ptr;
  1688.    while( curptr )
  1689.    {
  1690.        if( AFLAG( curptr ) )
  1691.            count++;
  1692.        curptr = FNEXT( curptr );   
  1693.    }
  1694.    return( count );
  1695. }
  1696.  
  1697.  
  1698. FON_PTR
  1699. FindFirstFont( FON_PTR ptr )
  1700. {
  1701.    FON_PTR curptr;
  1702.    
  1703.    curptr = ptr;
  1704.    while( curptr )
  1705.    {
  1706.        if( AFLAG( curptr ) && ( FTYPE( curptr ) == SPD_FONT ) )
  1707.            break;
  1708.        curptr = FNEXT( curptr );   
  1709.    }
  1710.    return( curptr );
  1711. }
  1712.  
  1713.  
  1714.  
  1715. /* CheckHotFront()
  1716.  *==========================================================================
  1717.  * Turn On/Off Remove and Config buttons in the ad_front tree
  1718.  */
  1719. void
  1720. CheckHotFront( FON_PTR Head_Node )
  1721. {
  1722.       if( IsActiveTree( ad_front ) )
  1723.       {
  1724.          if( IsChanged( Head_Node ) )
  1725.          {
  1726.            if( IsDisabled( FREMOVE ) )
  1727.           ChangeButton( ad_front, FREMOVE, TRUE );
  1728.        
  1729.            if( IsDisabled( FCONFIG ) )
  1730.           ChangeButton( ad_front, FCONFIG, TRUE );
  1731.      }
  1732.      else
  1733.      {
  1734.            if( !IsDisabled( FREMOVE ) )
  1735.           ChangeButton( ad_front, FREMOVE, FALSE );
  1736.        
  1737.            if( !IsDisabled( FCONFIG ) )
  1738.           ChangeButton( ad_front, FCONFIG, FALSE );
  1739.      }     
  1740.       }
  1741. }
  1742.  
  1743.  
  1744.  
  1745. /* CheckHotAvailable()
  1746.  *==========================================================================
  1747.  * Turn On/Off Remove and Config buttons in the ad_inactive tree
  1748.  */
  1749. void
  1750. CheckHotAvailable( FON_PTR Head_Node )
  1751. {
  1752.       if( IsActiveTree( ad_inactive ) )
  1753.       {
  1754.          if( IsChanged( Head_Node ) )
  1755.          {
  1756.            if( IsDisabled( IINSTALL ) )
  1757.            ChangeButton( ad_inactive, IINSTALL, TRUE );
  1758.        
  1759.            if( IsDisabled( ICONFIG ) )
  1760.            ChangeButton( ad_inactive, ICONFIG, TRUE );
  1761.      }
  1762.      else
  1763.      {
  1764.            if( !IsDisabled( IINSTALL ) )
  1765.            ChangeButton( ad_inactive, IINSTALL, FALSE );
  1766.        
  1767.            if( !IsDisabled( ICONFIG ) )
  1768.            ChangeButton( ad_inactive, ICONFIG, FALSE );
  1769.      }
  1770.      CheckSelectAll( TRUE );
  1771.       }
  1772. }
  1773.  
  1774.  
  1775.  
  1776.  
  1777. /* CheckHotPoints()
  1778.  *==========================================================================
  1779.  * Turn On/Off Delete Points button in the points tree
  1780.  */
  1781. void
  1782. CheckHotPoints( FON_PTR Head_Node )
  1783. {
  1784.       if( IsActiveTree( ad_points ) )
  1785.       {
  1786.          if( IsChanged( Head_Node ) )
  1787.          {
  1788.            if( IsDisabled( PNTDEL ) )
  1789.            ChangeButton( ad_points, PNTDEL, TRUE );
  1790.      }
  1791.      else
  1792.      {
  1793.            if( !IsDisabled( PNTDEL ) )
  1794.            ChangeButton( ad_points, PNTDEL, FALSE );
  1795.      }      
  1796.       }
  1797. }
  1798.